#-------------------Some Const Value----------------------------#
.equ  BOOTSTACK                 ,0x7C00
.equ  BOOTSEGMENT               ,0
.equ  BOOTOFFSET                ,0x7C00
.equ  ROOTENTRYSTARTSECTOR      ,19
.equ  ROOTENTRYSECTORNUMBER     ,14
.equ  ROOTENTRYBUFFEROFFSET     ,0x500
.equ  ROOTENTRYBUFFERSEGMENT    ,0
.equ  ROOTENTRYBUFFEREND        ,ROOTENTRYBUFFERSEGMENT*16+ROOTENTRYBUFFEROFFSET+ROOTENTRYSECTORNUMBER*512
.equ  ROOTENTRYBUFFERFULLADDRESS,ROOTENTRYBUFFERSEGMENT*16+ROOTENTRYBUFFEROFFSET
.equ  FATBUFFEROFFSET           ,0x500
.equ  FATBUFFERSEGMENT          ,0
.equ  FATSTARTSECTOR            ,1
.equ  FATSECTORNUMBER           ,9
.equ  FATBUFFERFULLADDRESS      ,FATBUFFERSEGMENT*16+FATBUFFEROFFSET
.equ  FATBUFFEREND              ,FATBUFFERFULLADDRESS+FATSECTORNUMBER*512
.equ  SECTOROFFSET              ,31
.equ  LOADERNAMELENGTH          ,11
.equ  LOADERBASEADDRESS         ,0
.equ  LOADEROFFSETADDRESS       ,0x7E00
.equ  SECTORNUMBERPERTRACK      ,18
.equ  DRIVER                    ,0
.equ  BIOSBOOTABLEFLAG          ,0xAA55
#------------------Global Functions Symbols---------------------#
.global Boot_Start

.code16
.section .text 
#---------------------Boot_Start--------------------------------#
Boot_Start:
#--------------------------------------------;
#I use the FAT12,although I don't like it.   ;
#Just because it's simple and easy to be used;
#--------------------------------------------;
  jmp  Label_Start
  nop

#--------------------------------------------;
#Many things I don't like                    ;
#--------------------------------------------;
bs_oemname:     .ascii   "HalfGod."
bpb_bytspersec: .2byte  512
bpb_secperclus: .byte   1
bpb_rsvdseccnt: .2byte  1
bpb_numfats:    .byte   2
bpb_rootentcnt: .2byte  224
bpb_totsec16:   .2byte  2880
bpb_media:      .byte   0xF0
bpb_fatsz16:    .2byte  9
bpb_secpertrk:  .2byte  18
bpb_numheads:   .2byte  2
bpb_hiddsec:    .4byte  0
bpb_totsec32:   .4byte  0
bs_drvnum:      .byte   0
bs_reserved1:   .byte   0
bs_bootsig:     .byte   0x29
bs_volid:       .4byte  0
bs_vollab:      .ascii  "Artist-0.01"
bs_filesystype: .ascii  "FAT12   "

Label_Start:
#--------------------------------------------;
#init the segment registers and stack        ;
#--------------------------------------------;
  movw %cs,%ax  
  movw %ax,%ds
  movw %ax,%es
  movw %ax,%ss
  movl $BOOTSTACK,%esp
#--------------------------------------------;
#Reset the floppy.                           ;
#--------------------------------------------;
  xorb %ah,%ah
  xorb %dl,%dl
  int  $0x13
#--------------------------------------------;
#Read the root entry directory               ;
#--------------------------------------------;
  pushw $ROOTENTRYBUFFEROFFSET
  pushw $ROOTENTRYBUFFERSEGMENT
  pushw $ROOTENTRYSECTORNUMBER
  pushw $ROOTENTRYSTARTSECTOR
  call  ReadSector
  addl  $8,%esp

#--------------------------------------------;
#To find the loader.bin entry                ;
#--------------------------------------------;
  movl  $ROOTENTRYBUFFERFULLADDRESS,%esi
Label_Search:
  movl  $LOADERNAMELENGTH,%ecx
  leal  loadername,%edi
  cld
  repe  cmpsb
  je    Label_Find
  andl  $0x0FFE0,%esi
  addl  $0x20,%esi
  cmpl  $ROOTENTRYBUFFEREND,%esi
  jg    LABEL_NOFIND
  jmp   Label_Search
#-----------------------------------;
#Find the file entry.               ;
#-----------------------------------;
Label_Find:
# Ok,we first push the first cluster serial number.
  pushw  15(%esi)
  pushw $FATBUFFEROFFSET
  pushw $FATBUFFERSEGMENT
  pushw $FATSECTORNUMBER
  pushw $FATSTARTSECTOR
  call  ReadSector
  addl  $8,%esp
#Let's get the first cluster serial number.
  popw  %ax

#--------------------------------------------------------------;
# We load the file to the LOADERBASEADDRESS:LOADEROFFSETADDRESS;
#--------------------------------------------------------------;
Label_Load:
  addw   $SECTOROFFSET,%ax
  pushw  loadnextaddress
  pushw  $LOADERBASEADDRESS
  pushw  $1
  pushw  %ax
  call   ReadSector
  addw   $512,loadnextaddress
  addl   $8,%esp
  subw   $SECTOROFFSET,%ax
  movw   $3,%bx
  mulw   %bx
  movw   $2,%bx
  divw   %bx
  addw   $0x500,%ax
  andl   $0x0000FFFF,%eax
  movw   (%eax),%bx
  cmpw   $0,%dx
  je     Label_Even
  shrw   $4,%bx
  jmp    Label_EndOrNo
Label_Even:
  andw   $0x0FFF,%bx
Label_EndOrNo:
  cmpw   $0xFF7,%bx
  jae    Label_End
  movw   %bx,%ax
  jmp    Label_Load

Label_End:
  jmp    $LOADERBASEADDRESS,$LOADEROFFSETADDRESS
LABEL_NOFIND:
  movw   $noloader,%ax
  movw   %ax,%bp
  movw   $11,%cx
  movw   $0x01301,%ax
  movw   $0x000C,%bx
  movb   $0,%dl
  int    $0x10
  jmp .
#------------------------------------------------------------------------;
#use the BIOS int 13h							 ;
#------------------------------------------------------------------------;
#reset the floppy 							 ;
#  ah=00h,								 ;
#  dl=driver serial number(0:A)						 ;
#------------------------------------------------------------------------;
#get the data from the floppy,						 ;
#and put it in the memory buffer according to the pointer es:bx		 ;
#  ah=02h,								 ;
#  al=the sector number wanted,						 ;
#  ch=cylinder(track) serial number,		 			 ;
#  cl=start sector serial number,					 ;
#  dh=magnetic head serial number,					 ;
#  dl=driver serial number(0:A,00H-7FH:floppy,80H-0FFH:Hard Disk),	 ;
#  es:bx->data buffer							 ;
#------------------------------------------------------------------------;
#the result:                                                             ;
#  CF=0 succeed ->AH=00H,AL=the sector number read                       ;
## else ->AL=the state code                                              ;
#------------------------------------------------------------------------;
#the 1.44MB floppy has two sides(megnetic head 0 and 1),each side has 80 ;
#(0-79) tracks,each track has 18 sectors(1-18).				 ;
#          The sector serial number      				 ;
#          ----------------------------=the quotient Q,the remainder R;  ;
#           sector number per track(18) 				 ;
#the cylinder serial number  =  Q>>1					 ;
#the magnetic head           =  Q&1					 ;
#the start sector            =  R+1					 ;
#------------------------------------------------------------------------;

#------------------------------------------------------------------------;
#    void  ReadSector(start sector 2byte,sector number 2byte,es,bx)      ;
#    !!!There is something wrong with the following function.Because the ;
#    int $0x13 ah=0x2 can read only one track ,it means it can read as   ;
#    many as 18 sectors.However we don't come across the problem so far. ;
#------------------------------------------------------------------------;
ReadSector:
  pushw %bp
  movw  %sp,%bp
  pusha
  pushw %es
  movw  4(%bp),%ax
  movb  $SECTORNUMBERPERTRACK,%bl
  divb  %bl
  movb  %al,%ch
  movb  %al,%dh
  movb  %ah,%cl
  shrb  %ch
  andb  $1,%dh
  addb  $1,%cl
  movb  $0x02,%ah
  movb  6(%bp),%al
  movw  8(%bp),%bx
  movw  %bx,%es
  movw  10(%bp),%bx
  movb  $DRIVER,%dl
Label_GoOnRead:
  int   $0x13
  jc Label_GoOnRead
  popw  %es
  popa
  popw  %bp
  ret

#---------------------------------------------;
#  Global variables.                          ;
#---------------------------------------------;
  loadername:      .ascii "LOADER  BIN"
  noloader:        .ascii "No loader!!"
  loadnextaddress: .word  LOADEROFFSETADDRESS
.org 510 
.word BIOSBOOTABLEFLAG
